/*
 * OptionsDialog.java
 */

package xq.ide.forms;

import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.JFrame;
import xq.api.XQException;
import xq.api.XQRequest;
import xq.api.XQResponse;
import xq.api.XQuery;
import xq.ide.ConnectionInfo;
import xq.ide.XQOptions;
import xq.ide.XQUtil;

/**
 *
 * @author ThorntonRP
 */
public class OptionsDialog extends javax.swing.JDialog {

	private static final long serialVersionUID = 1L;

	public OptionsDialog(JFrame parent, boolean modal) {
		super(parent, modal);
		initComponents();
		connectionListModel.addElement("<New Connection>");
		connectionList.setSelectedIndex(0);
		resourceClasspathPanel.addPropertyChangeListener("classpath", new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				XQOptions.getInstance().setResourceClasspath(resourceClasspathPanel.getClasspath());
			}
		});
		resourceClasspathPanel.setClasspath(XQOptions.getInstance().getResourceClasspath());
		bindingClasspathPanel.addPropertyChangeListener("classpath", new PropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				XQOptions.getInstance().setBindingClasspath(bindingClasspathPanel.getClasspath());
			}
		});
		bindingClasspathPanel.setClasspath(XQOptions.getInstance().getBindingClasspath());
		loadConnectionPreferences();
		setLocationRelativeTo(null);
		clearMessage();
	}

	private void clearMessage() {
		printMessage("", Color.BLACK);
	}

	private void printMessage(String message, Color color) {
		int lines = Math.min(message.split("\n").length, 10);
		messageTextArea.setForeground(color);
		messageTextArea.setText(message);
		messageTextArea.setRows(lines);
		messageTextArea.setCaretPosition(0);
		pack();
	}

	private void printError(String message) {
		printMessage(message, Color.RED);
	}

	private void printException(Exception ex) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		if (ex instanceof XQException) {
			pw.print(ex.getMessage());
		} else {
			ex.printStackTrace(pw);
		}
		printError(sw.toString());
	}

	private void loadConnectionPreferences() {
		List<ConnectionInfo> infoList = XQOptions.getInstance().getConnectionPreferences();
		for (ConnectionInfo connectionInfo : infoList) {
			connectionListModel.addElement(connectionInfo);
		}
	}

	private void saveConnectionPreferences() {
		List<ConnectionInfo> infoList = new ArrayList<ConnectionInfo>();
		Enumeration e = connectionListModel.elements();
		while (e.hasMoreElements()) {
			Object o = e.nextElement();
			if (o instanceof ConnectionInfo) {
				infoList.add((ConnectionInfo) o);
			}
		}
		XQOptions.getInstance().setConnectionPreferences(infoList);
	}

	private void updateFields() {
		Object selectedValue = connectionList.getSelectedValue();
		ResourceBundle bundle = ResourceBundle.getBundle("xq/ide/forms/Bundle"); // NOI18N
		if (selectedValue instanceof ConnectionInfo) {
			ConnectionInfo connectionInfo = (ConnectionInfo) selectedValue;
			testConnectionButton.setEnabled(true);
			removeConnectionButton.setEnabled(true);
			addConnectionButton.setText(bundle.getString("OptionsDialog.updateConnectionButton.text")); // NOI18N
			connectionNameTextField.setText(connectionInfo.getName());
			userNameTextField.setText(connectionInfo.getUserName());
			passwordTextField.setText(connectionInfo.getPassword());
			hostNameTextField.setText(connectionInfo.getHostName());
			portNumberTextField.setText(connectionInfo.getPortNumber());
		} else {
			testConnectionButton.setEnabled(false);
			removeConnectionButton.setEnabled(false);
			addConnectionButton.setText(bundle.getString("OptionsDialog.addConnectionButton.text")); // NOI18N
			connectionNameTextField.setText("");
			userNameTextField.setText("");
			passwordTextField.setText("");
			hostNameTextField.setText("");
			portNumberTextField.setText("");
		}
	}

	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        connectionListModel = new javax.swing.DefaultListModel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        directoryChooser = new javax.swing.JFileChooser();
        optionsTabbedPane = new javax.swing.JTabbedPane();
        connectionPanel = new javax.swing.JPanel();
        connectionNameLabel = new javax.swing.JLabel();
        connectionNameTextField = new javax.swing.JTextField();
        userNameLabel = new javax.swing.JLabel();
        userNameTextField = new javax.swing.JTextField();
        passwordLabel = new javax.swing.JLabel();
        passwordTextField = new javax.swing.JPasswordField();
        hostNameLabel = new javax.swing.JLabel();
        hostNameTextField = new javax.swing.JTextField();
        portNumberLabel = new javax.swing.JLabel();
        portNumberTextField = new javax.swing.JTextField();
        connectionScrollPane = new javax.swing.JScrollPane();
        connectionList = new javax.swing.JList();
        addConnectionButton = new javax.swing.JButton();
        removeConnectionButton = new javax.swing.JButton();
        testConnectionButton = new javax.swing.JButton();
        resourceClasspathPanel = new xq.ide.forms.ClasspathPanel();
        bindingClasspathPanel = new xq.ide.forms.ClasspathPanel();
        messageScrollPane = new javax.swing.JScrollPane();
        messageTextArea = new javax.swing.JTextArea();
        closeButton = new javax.swing.JButton();

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane1.setViewportView(jTextArea1);

        directoryChooser.setAcceptAllFileFilterUsed(false);
        directoryChooser.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY);

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("xq/ide/forms/Bundle"); // NOI18N
        setTitle(bundle.getString("OptionsDialog.title")); // NOI18N

        connectionNameLabel.setText(bundle.getString("OptionsDialog.connectionNameLabel.text")); // NOI18N
        connectionNameLabel.setFocusable(false);

        userNameLabel.setText(bundle.getString("OptionsDialog.userNameLabel.text")); // NOI18N
        userNameLabel.setFocusable(false);

        passwordLabel.setText(bundle.getString("OptionsDialog.passwordLabel.text")); // NOI18N
        passwordLabel.setFocusable(false);

        hostNameLabel.setText(bundle.getString("OptionsDialog.hostNameLabel.text")); // NOI18N
        hostNameLabel.setFocusable(false);

        portNumberLabel.setText(bundle.getString("OptionsDialog.portNumberLabel.text")); // NOI18N
        portNumberLabel.setFocusable(false);

        connectionScrollPane.setPreferredSize(new java.awt.Dimension(258, 124));

        connectionList.setModel(connectionListModel);
        connectionList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                connectionListValueChanged(evt);
            }
        });
        connectionScrollPane.setViewportView(connectionList);

        addConnectionButton.setText(bundle.getString("OptionsDialog.addConnectionButton.text")); // NOI18N
        addConnectionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addConnectionButtonActionPerformed(evt);
            }
        });

        removeConnectionButton.setText(bundle.getString("OptionsDialog.removeConnectionButton.text")); // NOI18N
        removeConnectionButton.setEnabled(false);
        removeConnectionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeConnectionButtonActionPerformed(evt);
            }
        });

        testConnectionButton.setText(bundle.getString("OptionsDialog.testConnectionButton.text")); // NOI18N
        testConnectionButton.setEnabled(false);
        testConnectionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                testConnectionButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout connectionPanelLayout = new javax.swing.GroupLayout(connectionPanel);
        connectionPanel.setLayout(connectionPanelLayout);
        connectionPanelLayout.setHorizontalGroup(
            connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, connectionPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(portNumberLabel, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(hostNameLabel, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(passwordLabel, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(userNameLabel, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(connectionNameLabel, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(addConnectionButton, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(portNumberTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
                    .addComponent(hostNameTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
                    .addComponent(passwordTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
                    .addComponent(userNameTextField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
                    .addComponent(connectionNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(connectionPanelLayout.createSequentialGroup()
                        .addComponent(removeConnectionButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 76, Short.MAX_VALUE)
                        .addComponent(testConnectionButton))
                    .addComponent(connectionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        connectionPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {addConnectionButton, removeConnectionButton});

        connectionPanelLayout.setVerticalGroup(
            connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(connectionPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(connectionPanelLayout.createSequentialGroup()
                        .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(connectionNameLabel)
                            .addComponent(connectionNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(userNameLabel)
                            .addComponent(userNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(passwordLabel)
                            .addComponent(passwordTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(hostNameLabel)
                            .addComponent(hostNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(portNumberLabel)
                            .addComponent(portNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(connectionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(connectionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(addConnectionButton)
                        .addComponent(removeConnectionButton))
                    .addComponent(testConnectionButton))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        optionsTabbedPane.addTab(bundle.getString("OptionsDialog.connectionPanel.TabConstraints.tabTitle"), connectionPanel); // NOI18N
        optionsTabbedPane.addTab(bundle.getString("OptionsDialog.resourceClasspathPanel.TabConstraints.tabTitle"), resourceClasspathPanel); // NOI18N
        optionsTabbedPane.addTab(bundle.getString("OptionsDialog.bindingClasspathPanel.TabConstraints.tabTitle"), bindingClasspathPanel); // NOI18N

        messageScrollPane.setBorder(null);

        messageTextArea.setColumns(20);
        messageTextArea.setEditable(false);
        messageTextArea.setRows(1);
        messageTextArea.setOpaque(false);
        messageScrollPane.setViewportView(messageTextArea);

        closeButton.setMnemonic('C');
        closeButton.setText(bundle.getString("OptionsDialog.closeButton.text")); // NOI18N
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(optionsTabbedPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 530, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(messageScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 465, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(closeButton)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(optionsTabbedPane, javax.swing.GroupLayout.PREFERRED_SIZE, 203, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(messageScrollPane)
                    .addComponent(closeButton))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void addConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addConnectionButtonActionPerformed
		clearMessage();
		Object selectedValue = connectionList.getSelectedValue();
		ConnectionInfo connectionInfo = null;
		if (selectedValue instanceof ConnectionInfo) {
			connectionInfo = (ConnectionInfo) selectedValue;
		}
		try {
			if (connectionInfo == null) {
				connectionInfo = new ConnectionInfo(
						connectionNameTextField.getText().trim(),
						userNameTextField.getText().trim(),
						new String(passwordTextField.getPassword()),
						hostNameTextField.getText().trim(),
						portNumberTextField.getText().trim(),
						"xcc://{0}:{1}@{2}:{3}" // NOI18N
						);
				connectionListModel.addElement(connectionInfo);
				connectionList.setSelectedIndex(connectionListModel.getSize() - 1);
			} else {
				connectionInfo.setName(connectionNameTextField.getText().trim());
				connectionInfo.setUserName(userNameTextField.getText().trim());
				connectionInfo.setPassword(new String(passwordTextField.getPassword()));
				connectionInfo.setHostName(hostNameTextField.getText().trim());
				connectionInfo.setPortNumber(portNumberTextField.getText().trim());
			}
			saveConnectionPreferences();
			updateFields();
		} catch (IllegalArgumentException ex) {
			printError(ex.getMessage());
		} catch (URISyntaxException ex) {
			printError(ex.getMessage());
		} catch (Exception ex) {
			printError(ex.toString());
		}
	}//GEN-LAST:event_addConnectionButtonActionPerformed

	private void removeConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeConnectionButtonActionPerformed
		clearMessage();
		int index = connectionList.getSelectedIndex();
		if (index > 0) {
			connectionListModel.remove(index);
			connectionList.setSelectedIndex(0);
			saveConnectionPreferences();
		}
	}//GEN-LAST:event_removeConnectionButtonActionPerformed

	private void connectionListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_connectionListValueChanged
		updateFields();
	}//GEN-LAST:event_connectionListValueChanged

	private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
		setVisible(false);
		dispose();
	}//GEN-LAST:event_closeButtonActionPerformed

	private void testConnectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_testConnectionButtonActionPerformed
		printMessage("Testing connection...", Color.GREEN.darker());
		Object selectedValue = connectionList.getSelectedValue();
		if (selectedValue instanceof ConnectionInfo) {
			final ConnectionInfo connectionInfo = (ConnectionInfo) selectedValue;
			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						XQuery xquery = new XQuery("\"Success\"");
						XQRequest request = new XQRequest(xquery);
						XQResponse<String> response = XQUtil.executeQuery(connectionInfo, request);
						printMessage(response.getResult(), Color.BLUE);
					} catch (Exception ex) {
						printException(ex);
					}
				}
			}).start();
		}
	}//GEN-LAST:event_testConnectionButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    javax.swing.JButton addConnectionButton;
    private xq.ide.forms.ClasspathPanel bindingClasspathPanel;
    private javax.swing.JButton closeButton;
    javax.swing.JList connectionList;
    javax.swing.DefaultListModel connectionListModel;
    private javax.swing.JLabel connectionNameLabel;
    javax.swing.JTextField connectionNameTextField;
    private javax.swing.JPanel connectionPanel;
    private javax.swing.JScrollPane connectionScrollPane;
    javax.swing.JFileChooser directoryChooser;
    private javax.swing.JLabel hostNameLabel;
    javax.swing.JTextField hostNameTextField;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JScrollPane messageScrollPane;
    javax.swing.JTextArea messageTextArea;
    private javax.swing.JTabbedPane optionsTabbedPane;
    private javax.swing.JLabel passwordLabel;
    javax.swing.JPasswordField passwordTextField;
    private javax.swing.JLabel portNumberLabel;
    javax.swing.JTextField portNumberTextField;
    javax.swing.JButton removeConnectionButton;
    private xq.ide.forms.ClasspathPanel resourceClasspathPanel;
    javax.swing.JButton testConnectionButton;
    private javax.swing.JLabel userNameLabel;
    javax.swing.JTextField userNameTextField;
    // End of variables declaration//GEN-END:variables
}
